﻿using System;
using System.Collections;
using System.Configuration;
using System.Drawing;
using System.Text;
using System.Web;
using System.Web.Configuration;
using System.Web.Hosting;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace Salient.Web.Administration.Security.Wizard
{
    public partial class wizardPermission : WebAdminUserControl
    {
        private const string APP_PATH = "WebAdminApplicationPath";
        private const string CURRENT_PATH = "WebAdminCurrentPath";
        private const string NO_DELETE_RULES = "WebAdminNoDeleteRules";
        private const string PARENT_RULE_COUNT = "WebAdminParentRuleCount";
        private const string RULES = "WebAdminRules";
        private const string SELECTED_ITEM = "WebAdminSelectedItem";
        private const string SELECTED_RULE = "WebAdminSelectedRule";


        public string CurrentPath
        {
            get { return (string) Session[CURRENT_PATH]; }
            set { Session[CURRENT_PATH] = value; }
        }

        public int ParentRuleCount
        {
            get
            {
                object obj = Session[PARENT_RULE_COUNT];
                return obj != null ? (int) obj : -1;
            }
            set { Session[PARENT_RULE_COUNT] = value; }
        }

        public ArrayList NotDeleteableRules
        {
            get { return (ArrayList) Session[NO_DELETE_RULES]; }
            set { Session[NO_DELETE_RULES] = value; }
        }

        public ArrayList Rules
        {
            get { return (ArrayList) Session[RULES]; }
            set { Session[RULES] = value; }
        }

        public int SelectedRule
        {
            get
            {
                object obj = Session[SELECTED_RULE];
                return obj != null ? (int) obj : -1;
            }
            set { Session[SELECTED_RULE] = value; }
        }


        public void GetNotDeletableRules(System.Configuration.Configuration config)
        {
            var notDeleteableAuth = (AuthorizationSection) config.GetSection("system.web/authorization");
            var arrNoDelete = new ArrayList();
            PropertyInformation propUsers = null;
            PropertyInformation propRoles = null;
            bool entryIsDeletable = false;
            int i = 0;
            foreach (AuthorizationRule entryKeep in notDeleteableAuth.Rules)
            {
                entryIsDeletable = true;
                propUsers = entryKeep.ElementInformation.Properties["users"];
                propRoles = entryKeep.ElementInformation.Properties["roles"];

                if (propUsers != null)
                {
                    if (propUsers.ValueOrigin == PropertyValueOrigin.Inherited)
                    {
                        entryIsDeletable = false;
                    }
                }

                if (propRoles != null && entryIsDeletable)
                {
                    if (propRoles.ValueOrigin == PropertyValueOrigin.Inherited)
                    {
                        entryIsDeletable = false;
                    }
                }

                if (!entryIsDeletable)
                {
                    // store the index in here as to which one is not deletable
                    arrNoDelete.Add(i);
                }

                i++;
            }

            Session[NO_DELETE_RULES] = arrNoDelete;
        }

        public void AddPermissionRule(string currentPath, TextBox userName, ListControl roles, CheckBox userRadio,
                                      CheckBox roleRadio, CheckBox allUsersRadio, CheckBox anonymousUsersRadio,
                                      CheckBox grantRadio, CheckBox denyRadio)
        {
            System.Configuration.Configuration config = ((WebAdminPage) Page).OpenWebConfiguration(currentPath, true);
            var auth = (AuthorizationSection) config.GetSection("system.web/authorization");

            var rule =
                new AuthorizationRule(grantRadio.Checked ? AuthorizationRuleAction.Allow : AuthorizationRuleAction.Deny);

            if (userRadio.Checked)
            {
                rule.Users.Add(userName.Text);
            }
            else if (roleRadio.Checked)
            {
                rule.Roles.Add(roles.SelectedItem.Text);
            }
            else if (allUsersRadio.Checked)
            {
                rule.Users.Add("*");
            }
            else if (anonymousUsersRadio.Checked)
            {
                rule.Users.Add("?");
            }

            auth.Rules.Add(rule);
            ((WebAdminPage) Page).SaveConfig(config);
        }

        protected void AddRule(object sender, EventArgs e)
        {
            if (!((WebAdminPage) Page).IsRuleValid(placeholderValidator, userRadio, userName, roleRadio, roles))
            {
                return;
            }
            AddPermissionRule(CurrentPath, userName, roles, userRadio, roleRadio, allUsersRadio, anonymousUsersRadio,
                              grantRadio, denyRadio);
            BindGrid();
        }

        public string GetToolTip(string resourceName, string itemName)
        {
            var tempString = (string) GetLocalResourceObject(resourceName);
            return String.Format((string) GetGlobalResourceObject("GlobalResources", "ToolTipFormat"), tempString,
                                 itemName);
        }

        private void BindGrid()
        {
            string curPath = CurrentPath;
            string parentPath = WebAdminPage.GetParentPath(curPath);

            System.Configuration.Configuration config = ((WebAdminPage) Page).OpenWebConfiguration(curPath, true);
            var auth = (AuthorizationSection) config.GetSection("system.web/authorization");

            System.Configuration.Configuration parentConfig = ((WebAdminPage) Page).OpenWebConfiguration(parentPath,
                                                                                                         true);
            var parentAuth = (AuthorizationSection) parentConfig.GetSection("system.web/authorization");
            ParentRuleCount = parentAuth.Rules.Count;

            GetNotDeletableRules(config);

            var arr = new ArrayList();
            foreach (AuthorizationRule entry in auth.Rules)
            {
                arr.Add(entry);
            }
            Rules = arr;
            dataGrid.DataSource = arr;
            dataGrid.DataBind();
            if (dataGrid.SelectedRow != null)
            {
                UpdateRowColors(dataGrid, dataGrid.Rows[dataGrid.SelectedRow.RowIndex]);
            }
        }

        public void DeleteRule(object sender, EventArgs e)
        {
            var button = (LinkButton) sender;
            var item = (GridViewRow) button.Parent.Parent;
            var rule = (AuthorizationRule) Rules[item.RowIndex];
            var builder = new StringBuilder();
            builder.Append(rule.Action);
            int i = 0;
            foreach (string u in rule.Users)
            {
                if (i > 0)
                {
                    builder.Append(", " + u);
                }
                else
                {
                    builder.Append(" " + u);
                }
                i++;
            }
            i = 0;
            foreach (string r in rule.Roles)
            {
                if (i > 0)
                {
                    builder.Append(", " + r);
                }
                else
                {
                    builder.Append(" " + r);
                }
                i++;
            }

            confirmation.DialogContent.Text = String.Format((string) GetLocalResourceObject("AreYouSure"), builder);
            mv1.ActiveViewIndex = 1;
            Session["ItemIndex"] = item.RowIndex;
            ((WizardPage) Page).DisableWizardButtons();
        }

        public void OK_Click(object sender, EventArgs e)
        {
            Rules.RemoveAt((int) Session["ItemIndex"]);
            UpdateRules();
            BindGrid();
            mv1.ActiveViewIndex = 0;
            ((WizardPage) Page).EnableWizardButtons();
        }

        public void Cancel_Click(object sender, EventArgs e)
        {
            mv1.ActiveViewIndex = 0;
            ((WizardPage) Page).EnableWizardButtons();
        }

        private string GetRoles(object val, bool appendImg)
        {
            var builder = new StringBuilder();
            var rule = (AuthorizationRule) val;
            if (rule.Roles.Count == 0)
            {
                return String.Empty;
            }
            for (int i = 0; i < rule.Roles.Count; i++)
            {
                if (i > 0)
                {
                    builder.Append(", ");
                }
                string role = rule.Roles[i];
                if (role == "*")
                {
                    role = (string) GetLocalResourceObject("BracketAll");
                }
                builder.Append(role);
            }
            if (appendImg)
            {
                var builder2 = new StringBuilder();
                builder2.Append("<img src=\"../../Images/image2.gif\" alt=\"" +
                                (string) GetGlobalResourceObject("GlobalResources", "RoleGif") + " [" + builder + "]" +
                                "\"/> ");
                builder2.Append(builder.ToString());
                return builder2.ToString();
            }
            else
            {
                return builder.ToString();
            }
        }


        private string GetUsers(object val, bool appendImg)
        {
            var builder = new StringBuilder();
            var rule = (AuthorizationRule) val;
            if (rule.Users.Count == 0)
            {
                return String.Empty;
            }
            for (int i = 0; i < rule.Users.Count; i++)
            {
                if (i > 0)
                {
                    builder.Append(", ");
                }
                string user = rule.Users[i];
                if (user == "?")
                {
                    user = (string) GetLocalResourceObject("BracketAnonymous");
                }
                else if (user == "*")
                {
                    user = (string) GetLocalResourceObject("BracketAll");
                }
                builder.Append(user);
            }
            if (appendImg)
            {
                var builder2 = new StringBuilder();
                builder2.Append("<img src=\"../../Images/image1.gif\" alt=\"" +
                                (string) GetGlobalResourceObject("GlobalResources", "UserGif") + " [" + builder + "]" +
                                "\"/> ");
                builder2.Append(builder.ToString());
                return builder2.ToString();
            }
            else
            {
                return builder.ToString();
            }
        }

        public string GetAction(object val)
        {
            var rule = (AuthorizationRule) val;
            string ruleAction = "";
            if (rule.Action == AuthorizationRuleAction.Allow)
            {
                ruleAction = (string) GetLocalResourceObject("Allow");
            }
            else if (rule.Action == AuthorizationRuleAction.Deny)
            {
                ruleAction = (string) GetLocalResourceObject("Deny");
            }
            return ruleAction;
        }

        public string GetUsersAndRoles(object val, bool appendImg)
        {
            return GetUsers(val, appendImg) + GetRoles(val, appendImg);
        }

        public bool IsEntryDeleteable(int rowIndex)
        {
            bool entryIsDeleteable = false;
            if (rowIndex < Rules.Count - ParentRuleCount)
            {
                entryIsDeleteable = true;
            }
            if (!entryIsDeleteable)
            {
                return entryIsDeleteable;
            }
            foreach (int index1 in NotDeleteableRules)
            {
                if (index1 == rowIndex)
                {
                    entryIsDeleteable = false;
                }
            }
            return entryIsDeleteable;
        }

        public bool IsIE()
        {
            HttpBrowserCapabilities caps = Page.Request.Browser;
            bool isIE = (caps.Type.IndexOf("IE") > -1);
            return isIE;
        }

        public void ItemDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowIndex >= Rules.Count - ParentRuleCount)
            {
                return;
            }
            DataControlRowType itemType = e.Row.RowType;
            if ((itemType == DataControlRowType.Pager) ||
                (itemType == DataControlRowType.Header) ||
                (itemType == DataControlRowType.Footer))
            {
                return;
            }

            if (IsIE())
            {
                if (IsEntryDeleteable(e.Row.RowIndex))
                {
                    // if netscape, then selecting the the row
                    // will not allow the DeleteRule to fire
                    foreach (Control c in e.Row.Cells[0].Controls)
                    {
                        var button = c as LinkButton;
                        if (button == null)
                        {
                            continue;
                        }
                        e.Row.Attributes["onclick"] = Page.GetPostBackClientHyperlink(button, "");
                    }
                }
            }
        }

        public string GetVirtualPath(string path)
        {
            if (path == null)
            {
                return null; // REVIEW: Should not happen.
            }
            return path.Substring("IIS://localhost/W3SVC/1/ROOT".Length);
        }

        private string GetDirectory(string path)
        {
            if (path == null)
            {
                return null;
            }

            if (path.LastIndexOf('/') == -1)
            {
                return "/";
            }

            return path.Substring(path.LastIndexOf('/') + 1);
        }

        protected override void OnInit(EventArgs e)
        {
            if (!IsPostBack)
            {
                var appPath = (string) Session[APP_PATH];
                var n = new TreeNode(GetDirectory(appPath), appPath);
                tv.Nodes.Add(n);
                n.Selected = true;
                PopulateChildren(n, null);
                CurrentPath = appPath;
            }

            if (!((WebAdminPage) Page).IsRoleManagerEnabled())
            {
                var item = new ListItem((string) GetLocalResourceObject("RolesDisabled"));
                roles.Items.Add(item);
                roles.Enabled = false;
                roleRadio.Enabled = false;
                roleRadio.Checked = false;
                userRadio.Checked = true;
                base.OnInit(e);
                return;
            }
            roles.DataSource = ((WebAdminPage) Page).CallWebAdminHelperMethod(false, "GetAllRoles", new object[] {},
                                                                              null);
            roles.DataBind();
            if (roles.Items.Count == 0)
            {
                var item = new ListItem((string) GetLocalResourceObject("NoRoles"));
                roles.Items.Add(item);
                roles.Enabled = false;
                roleRadio.Enabled = false;
                roleRadio.Checked = false;
                userRadio.Checked = true;
            }
            base.OnInit(e);
        }

        public void Page_Load()
        {
            Hashtable coll = ((WebAdminPage) Page).UserCollection;
            if (coll != null && coll.Count > 0)
            {
                bool first = true;
                var builder = new StringBuilder();
                foreach (string s in coll.Keys)
                {
                    if (!first)
                    {
                        builder.Append(",");
                    }
                    else
                    {
                        first = false;
                    }
                    builder.Append(s);
                }
                userName.Text = builder.ToString();
                ((WebAdminPage) Page).ClearUserCollection();
            }
            BindGrid();
        }

        public void Page_Init()
        {
            confirmation.DialogTitle.Text = (string) GetLocalResourceObject("DeleteRule");
            confirmation.LeftButton.Click += OK_Click;
            confirmation.RightButton.Click += Cancel_Click;
            dataGrid.HeaderStyle.HorizontalAlign = DirectionalityHorizontalAlign;
        }

        private void PopulateChildren(TreeNode parent, string selectNodeValue)
        {
            if (parent.ChildNodes.Count == 0)
            {
                VirtualDirectory vdir = ((WebAdminPage) Page).GetVirtualDirectory(parent.Value);
                foreach (VirtualDirectory childVdir in vdir.Directories)
                {
                    string childValue = parent.Value + "/" + childVdir.Name;
                    var newNode = new TreeNode(childVdir.Name, childValue);
                    if (selectNodeValue != null && childValue == selectNodeValue)
                    {
                        //newNode.Selected = true;
                        newNode.SelectAction = TreeNodeSelectAction.Select;
                    }
                    parent.ChildNodes.Add(newNode);
                }
            }
        }


        public void SearchForUsers(object sender, EventArgs e)
        {
            ((WizardPage) Page).SaveActiveView();
            Server.Transfer("../users/findusers.aspx");
        }

        private void SetItemColorRecursive(Control c, Color col)
        {
            foreach (Control child in c.Controls)
            {
                var button = child as LinkButton;
                if (button != null)
                {
                    button.ForeColor = col;
                }
                var label = child as Label;
                if (label != null)
                {
                    label.ForeColor = col;
                }
                SetItemColorRecursive(child, col);
            }
        }

        protected void TreeNodeExpanded(Object sender, TreeNodeEventArgs e)
        {
            foreach (TreeNode child in e.Node.ChildNodes)
            {
                PopulateChildren(child, null);
            }
        }

        protected void TreeNodeSelected(object sender, EventArgs e)
        {
            CurrentPath = ((TreeView) sender).SelectedNode.Value;
            BindGrid();
        }

        public void UpdateRowColors(Control dataGrid, Control item)
        {
            if (item == null)
            {
                // unexpected condition -exit gracefully
                return;
            }
            var prevItemID = (string) Session[SELECTED_ITEM];
            if (prevItemID != null)
            {
                var prevItem = (GridViewRow) (dataGrid).FindControl(prevItemID);
                if (prevItem != null)
                {
                    // REVIEW
                    SetItemColorRecursive(prevItem, Color.Black);
                    // prevButton.ForeColor = Color.Black;
                }
            }

            SetItemColorRecursive(item, Color.White);
            // Review: best practice for a naming container inside a user control.
            string id = item.UniqueID;
            int i = id.IndexOf((dataGrid).ID);
            id = id.Substring(i);
            i = id.IndexOf("$");
            id = id.Substring(i + 1);
            Session[SELECTED_ITEM] = id;
        }

        private void UpdateRules()
        {
            ArrayList rules = Rules;
            System.Configuration.Configuration config = ((WebAdminPage) Page).OpenWebConfiguration(CurrentPath, true);
            var auth = (AuthorizationSection) config.GetSection("system.web/authorization");
            auth.Rules.Clear();
            foreach (AuthorizationRule rule in rules)
            {
                auth.Rules.Add(rule);
            }

            ((WebAdminPage) Page).SaveConfig(config);
        }
    }
}